﻿//===========================[ 8 / 2 / 2011 LVI ]=============================
//				Copyright c Vitaly Lyaschenko <SkyChameleon@gmail.com>
//								Source file
// Purpose: 
//=============================================================================
#include "Entity.h"
#include "cTimer.h"
#include "cRenderDevice.h"

extern cShaderProgram  *currenProgram;
extern cRenderDevice   *pRender;
//extern cProgramManager *pProgramManager;

Shape::Shape() : 
    m_Model(NULL),
	m_buildFlag(false)
{	}

Shape::~Shape()
{
	release();
}

void Shape::init( const std::string& fileName, bool buildFlag )
{
	std::string strToMesh = cFileManager::lookUpPath( fileName.c_str() );

	m_Model = cMeshesManager::loadMesh( strToMesh );

	//cMeshesManager::optimize( m_Model,WELD_VERTICES );

	if (buildFlag)
		build();
}

void Shape::build()
{
	// если ранее модель не "собиралась"
	//uint program = cProgramManager::at("base")->getID();
	//uint program = currenProgram->getID();
	if (!m_buildFlag)
	{
		//for ( int i=0; i != m_Model->getNumMesh(); i++ )
		//{   
			int sizeofVert = sizeof(Vertex_PNT) * m_Model->meshes[0]->getNumVertices();
			int sizeofIndx = sizeof(_16ubit) * m_Model->meshes[0]->getNumIndices();
			void *dataVert = m_Model->meshes[0]->m_Vertices.data();
			void *dataIndx = m_Model->meshes[0]->m_Indices.data();

			//// создание и биндинг 1 VAO для части модели
			//m_VAO.push_back( pRender->createVArray() );

			//// создаем VBO(Vertex Buffer Object) для позиции вершин
			//m_VBO_Pos.push_back( pRender->createVBuffer( sizeofVert,dataVert ) );
			//pRender->setAttrPtr(VERT_POSITION,3,sizeof(Vertex_PNT),(void *) 0);

			//// создаем VBO(Vertex Buffer Object) для нормалей
			//m_VBO_Normal.push_back( pRender->createVBuffer( sizeofVert,dataVert ) );
			//pRender->setAttrPtr(VERT_NORMAL,3,sizeof(Vertex_PNT),(void *) (sizeof(float) * 3));

			//// создаем VBO(Vertex Buffer Object) для текстурных координат
			//m_VBO_TexCoor.push_back( pRender->createVBuffer( sizeofVert,dataVert ) );
			//pRender->setAttrPtr(VERT_TEXCOORD,2,sizeof(Vertex_PNT),(void *) (sizeof(float) * 6));

			//// создаем VBO(Vertex Buffer Object) для индексов
			//m_VBO_Indices.push_back( pRender->createVBufferEl( sizeofIndx,dataIndx ) );

			//m_VAO.back()->Unbind();

			m_VAO.Create();
			m_VAO.Bind();

			m_VBO_Pos.Create( gl_ARRAY_BUFFER,sizeofVert,dataVert,gl_STATIC_DRAW );
			pRender->setAttrPtr( VERT_POSITION, 3, sizeof(Vertex_PNT), (void *)0 ); 

			m_VBO_Normal.Create( gl_ARRAY_BUFFER,sizeofVert,dataVert,gl_STATIC_DRAW );
			pRender->setAttrPtr(VERT_NORMAL, 3, sizeof(Vertex_PNT), (void *) (sizeof(float) * 3) );

			m_VBO_TexCoor.Create(gl_ARRAY_BUFFER,sizeofVert,dataVert,gl_STATIC_DRAW);
			pRender->setAttrPtr( VERT_TEXCOORD, 2, sizeof(Vertex_PNT), (void *) (sizeof(float) * 6) );

			m_VBO_Indices.Create( gl_ELEMENT_ARRAY_BUFFER,sizeofIndx, dataIndx, gl_STATIC_DRAW );

			// освобождаем(unbind) VAO
			m_VAO.Unbind();
		/*}*/
	}
	m_buildFlag = true;
}

void Shape::draw()
{

	//auto it = m_VAO.begin();
	//for (int i=0; it != m_VAO.end(); it++,i++)
	//{
	int coutIndx = m_Model->meshes[0]->getNumIndices();

	//	(*it)->Bind();
	//	pRender->drawElements16(coutIndx);
	//	(*it)->Unbind();
	//}

	m_VAO.Bind();

	//pRender->setModePromitiveDraw( Triangles );
	pRender->drawElements16(m_Model->meshes[0]->m_Indices.size());
	//glDrawElements( GL_TRIANGLES,  , GL_UNSIGNED_SHORT, NULL );
	//(*it)->unbind();
	m_VAO.Unbind();
	//glBindVertexArray( 0 );
}

///////////////////////////////////////////////////////////////////////////
// освобождение всех ресурсов
void Shape::release()
{
	if (!m_buildFlag)
		return;

	//int numPart = m_Mesh->getNumPart();

	//for ( int i = 0; i != numPart; i++ )
	//{
	//	// удаление всех VBO модели
	//	m_VBO_Pos.at(i)->release();
	//	m_VBO_Normal.at(i)->release();
	//	m_VBO_TexCoor.at(i)->release();
	//	m_VBO_Indices.at(i)->release();

	//	// удаление VAO
	//	m_VAO.at(i)->release();
	//}

	//m_VAO.clear();
	//m_VBO_Pos.clear();
	//m_VBO_Normal.clear();
	//m_VBO_TexCoor.clear();
	//m_VBO_Indices.clear();

	SAFE_DELETE(m_Model);

	m_buildFlag = false;
}

void Shape::update()
{

	float deltaTime = cTimer::getFrameTime();
	// для хранения двух углов поворота
	static vec3 cubeRotation;

	// зададим углы поворота куба с учетом времени
	if ((cubeRotation.x  += 0.3f * deltaTime) > 360.0f)
		cubeRotation.x -= 360.0f;

	if ((cubeRotation.y += 10.5f * deltaTime) > 360.0f)
		cubeRotation.y -= 360.0f;

	if ((cubeRotation.z += 17.7f * deltaTime) > 360.0f)
		cubeRotation.z -= 360.0f;

	// расчитать матрицу вращения
	mtrModel = _mtl::fromEuler(cubeRotation.x, cubeRotation.y, cubeRotation.z);
}
